package com.cskaoyan.wordmemorize.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cskaoyan.wordmemorize.auth.StpKit;
import com.cskaoyan.wordmemorize.converter.UserConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.LevelPrivilegeDTO;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.*;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserRemindCommand;
import com.cskaoyan.wordmemorize.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    UserMapper userMapper;
    @Autowired
    UserRemindMapper userRemindMapper;
    @Autowired
    UserConverter userConverter;
    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;
    @Autowired
    LevelMapper levelMapper;
    @Autowired
    LevelPrivilegeMapper levelPrivilegeMapper;
    @Autowired
    UserCheckinStatisticsMapper userCheckinStatistics;

    @Override
    public UserDTO getUserInfo(Long userId) {
        // 查询基本信息
        UserDO userDO = userMapper.getUserInfo(userId);

        return userConverter.userDO2DTO(userDO);
    }

    @Override
    public NextLevelDTO getUserNextDTO(Long userId) {
        // 1. 查询用户信息
        UserDO user = userMapper.selectById(userId);
        if (user == null || user.getIsDeleted() == 1) {
            throw new RuntimeException("用户不存在或已被删除");
        }

        // 2. 获取用户当前等级值
        Integer currentLevelValue = user.getLevelValue();
        if (currentLevelValue == null) {
            currentLevelValue = 0; // 默认0级
        }

        // 3. 12级用户直接返回0天（连续签到类型）
        if (currentLevelValue == 12) {
            NextLevelDTO nextLevelDTO=new NextLevelDTO();
            nextLevelDTO.setSignType(1);
            nextLevelDTO.setRemainDays(0);
            return nextLevelDTO;
        }

        // 4. 查询当前等级配置
        LevelDO currentLevel = levelMapper.selectById(currentLevelValue+1);
        if (currentLevel == null) {
            throw new RuntimeException("当前等级配置不存在");
        }

        // 5. 查询下一等级配置（当前等级+1）
        LevelDO nextLevel = levelMapper.selectById(currentLevelValue + 2);
        if (nextLevel == null) {
            throw new RuntimeException("下一等级配置不存在");
        }

        // 6. 获取用户签到统计
        UserCheckinStatisticsDO stats = userCheckinStatistics.selectById(userId);
        if (stats == null) {
            // 初始化默认统计
            stats = UserCheckinStatisticsDO.builder()
                    .totalDays(0)
                    .curContinuousDays(0)
                    .build();
        }

        // 7. 根据不同等级范围计算剩余天数
        Integer remainDays = 0;
        Integer signType = null;

        if (currentLevelValue >= 0 && currentLevelValue <= 5) {
            // 0-5级：使用累计签到
            signType = 2;
            int totalDays = stats.getTotalDays() != null ? stats.getTotalDays() : 0;
            int currentRequired = currentLevel.getCheckInDays() != null ? currentLevel.getCheckInDays() : 0;

            if (totalDays < currentRequired) {
                // 购买升级用户：使用等级差值
                remainDays = nextLevel.getCheckInDays() - currentRequired;
            } else {
                // 正常签到用户：使用实际差值
                remainDays = nextLevel.getCheckInDays() - totalDays;
            }
        } else if (currentLevelValue >= 6 && currentLevelValue <= 11) {
            // 6-11级：使用连续签到
            signType = 1;
            int continuousDays = stats.getCurContinuousDays() != null ? stats.getCurContinuousDays() : 0;
            remainDays = nextLevel.getCheckInDays() - continuousDays;
        }

        // 8. 确保剩余天数非负
        remainDays = Math.max(remainDays, 0);
        NextLevelDTO nextLevelDTO=new NextLevelDTO();
        nextLevelDTO.setSignType(signType);
        nextLevelDTO.setRemainDays(remainDays);

        // 9. 构建返回对象
        return nextLevelDTO;
    }

    @Override
    public DisplayUserLevelDTO getUserLevelInfo(Long userId) {
        // 1. 查询所有等级信息
        QueryWrapper<LevelDO> levelQuery = new QueryWrapper<>();
        levelQuery.eq("is_deleted", 0);
        levelQuery.orderByAsc("level_value");
        List<LevelDO> levels = levelMapper.selectList(levelQuery);
        // 2. 查询所有特权信息
        QueryWrapper<LevelPrivilegeDO> privilegeQuery = new QueryWrapper<>();
        privilegeQuery.eq("is_deleted", 0);
        List<LevelPrivilegeDO> privileges = levelPrivilegeMapper.selectList(privilegeQuery);
        // 3. 按等级值分组特权
        Map<Integer, List<LevelPrivilegeDTO>> privilegeMap = new HashMap<>();
        for (LevelPrivilegeDO privilege : privileges) {
            LevelPrivilegeDTO dto = new LevelPrivilegeDTO();
            dto.setId(String.valueOf(privilege.getId()));
            dto.setPrivilegeCode(privilege.getPrivilegeCode());
            dto.setPrivilegeName(privilege.getPrivilegeName());
            dto.setUseType(privilege.getUseType());
            dto.setRequireVocBound(privilege.getRequireVocBound());
            dto.setFreeCount(privilege.getFreeCount());
            dto.setExchangeType(null);
            dto.setLevelValue(privilege.getLevelValue());
            dto.setDescription(privilege.getDescription());

            int levelValue = privilege.getLevelValue();
            if (!privilegeMap.containsKey(levelValue)) {
                privilegeMap.put(levelValue, new ArrayList<>());
            }
            privilegeMap.get(levelValue).add(dto);
        }
        // 4. 构建等级DTO列表
        List<LevelPageDTO> allLevels = new ArrayList<>();
        for (LevelDO level : levels) {
            LevelPageDTO dto = new LevelPageDTO();
            dto.setId(String.valueOf(level.getId()));
            dto.setLevelName(level.getLevelName());
            dto.setLevelValue(level.getLevelValue());
            dto.setCheckInDays(level.getCheckInDays());
            dto.setCheckInType(level.getCheckInType());
            dto.setUnlockPrice(level.getUnlockPrice());
            dto.setDescription(level.getDescription());

            // 获取该等级对应的特权
            List<LevelPrivilegeDTO> levelPrivileges = privilegeMap.get(level.getLevelValue());
            if (levelPrivileges == null) {
                levelPrivileges = new ArrayList<>();
            }
            dto.setLevelPrivileges(levelPrivileges);

            allLevels.add(dto);
        }
        // 5. 查询用户当前等级
        QueryWrapper<UserDO> userQuery = new QueryWrapper<>();
        userQuery.select("level_value");
        userQuery.eq("id", userId);
        userQuery.eq("is_deleted", 0);
        UserDO user = userMapper.selectOne(userQuery);

        int currentLevel = 0;
        if (user != null && user.getLevelValue() != null) {
            currentLevel = user.getLevelValue();
        }

        // 6. 将等级分为已达成和未达成
        List<LevelPageDTO> achievedLevels = new ArrayList<>();
        List<LevelPageDTO> unachievedLevels = new ArrayList<>();

        for (LevelPageDTO level : allLevels) {
            if (level.getLevelValue() <= currentLevel) {
                achievedLevels.add(level);
            } else {
                unachievedLevels.add(level);
            }
        }

        // 7. 构建返回对象
        DisplayUserLevelDTO result = new DisplayUserLevelDTO();
        result.setNowLevel(achievedLevels);
        result.setUpperLevel(unachievedLevels);
        return result;
    }

    @Override
    public void updateVocCountOfDay(Long userId, Integer count) {
        if (userId == null || count == null || count <= 0) {
            throw new IllegalArgumentException("用户ID不能为空或单词数量非法!");
        }

        UpdateWrapper<UserDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", userId)
                .set("voc_count_of_day", count);

        int affectedRows = userMapper.update(null, updateWrapper);

        if (affectedRows == 0) {
            throw new RuntimeException("更新每日单词量失败，用户可能不存在，用户ID: " + userId);
        }
    }

    @Override
    public void updateUserRemind(UserRemindCommand command,Long userId) {
        UpdateWrapper<UserRemindDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", userId);
        // 处理提醒时间，字符串转LocalTime
        if (command.getRemindTime() != null) {
            try {
                LocalTime remindTime = LocalTime.parse(command.getRemindTime());
                updateWrapper.set("remind_time", remindTime);
            } catch (DateTimeParseException e) {
                throw new IllegalArgumentException("提醒时间格式错误，正确格式为HH:mm");
            }
        }
        // 系统通知状态
        if (command.getSysStatus() != null) {
            updateWrapper.set("sys_status", command.getSysStatus());
        }

        // 消息通知状态
        if (command.getMessageStatus() != null) {
            updateWrapper.set("message_status", command.getMessageStatus());
        }

        // 执行更新操作
        int updated = userRemindMapper.update(null, updateWrapper);
        if (updated == 0) {
            throw new RuntimeException("未找到对应的用户提醒记录，更新失败");
        }
    }

    @Override
    public UserRemindDTO getUserRemind(Long userId) {
        return null;
    }


    @Override
    public void messageRemind() {


    }

    @Override
    public PageDTO<DisplayUserVocBoundLogDTO> getUserVocBoundLog(PageRequest pageRequest, Long userId) {
        // 无条件查询所有日志
        List<UserVocBoundLogDO> allLogs = userMapper.selectUserVocBoundLogs(userId);
        long totalCount = allLogs.size();

        // 处理分页参数
        List<UserVocBoundLogDO> pageLogs;
        if (pageRequest.getPageNum() != null && pageRequest.getCount() != null) {
            // 计算分页索引
            int pageNum = Math.max(pageRequest.getPageNum(), 1);
            int pageSize = pageRequest.getCount();
            int startIndex = (pageNum - 1) * pageSize;
            int endIndex = Math.min(startIndex + pageSize, (int) totalCount);
            pageLogs = allLogs.subList(startIndex, endIndex);

        } else {
            // 无分页参数时返回全部数据
            pageLogs = allLogs;
        }
        return userConverter.userVocBoundLogPage2PageDTO(userConverter.userVocBoundLogDTOs2DisplayDTOs(pageLogs),totalCount);

}

    @Override
    public UserVocBoundStatisticsDTO getUserVocBoundStatistics(Long userId) {
        QueryWrapper<UserVocBoundStatisticsDO> queryWrapper = new QueryWrapper<>();
        // 设置查询条件：userId 相等且未删除
        queryWrapper.eq("user_id", userId)
                .eq("is_deleted", 0);
        // 执行查询
        UserVocBoundStatisticsDO statistics = userVocBoundStatisticsMapper.selectOne(queryWrapper);
        // 如果查询结果为空，返回 null
        if (statistics == null) {
            return null;
        }
        // 将实体对象转换为 DTO 对象
        return userConverter.userVocBoundStatisticsDO2DisplayDTO(statistics);
    }


    @Override
    public UserPageDTO getUserPage(Long userId) {

        return userMapper.getUserPage(userId);
    }
}
